import axios from 'axios'
import type { AxiosInstance, AxiosRequestConfig, AxiosResponse, AxiosError } from 'axios'

// 响应数据接口
export interface ApiResponse<T = any> {
  code: number
  data: T
  message: string
  success: boolean
}

// 请求配置接口
export interface RequestConfig extends AxiosRequestConfig {
  showLoading?: boolean
  showError?: boolean
}

class HttpClient {
  private instance: AxiosInstance
  private baseURL = '/api'

  constructor() {
    this.instance = axios.create({
      baseURL: this.baseURL,
      timeout: 10000,
      headers: {
        'Content-Type': 'application/json'
      }
    })

    this.setupInterceptors()
  }

  private setupInterceptors() {
    // 请求拦截器
    this.instance.interceptors.request.use(
      (config) => {
        // 添加token
        const token = localStorage.getItem('token')
        if (token) {
          config.headers.Authorization = `Bearer ${token}`
        }

        // 显示loading
        const customConfig = config as RequestConfig
        if (customConfig.showLoading !== false) {
          // 这里可以集成loading组件
          console.log('Loading start...')
        }

        return config
      },
      (error: AxiosError) => {
        console.error('Request error:', error)
        return Promise.reject(error)
      }
    )

    // 响应拦截器
    this.instance.interceptors.response.use(
      (response: AxiosResponse<ApiResponse>) => {
        // 隐藏loading
        console.log('Loading end...')

        const { data } = response

        // 如果后端返回的是统一的 ApiResponse 结构，按原有逻辑处理
        if (data && typeof data === 'object' && ('success' in data || 'code' in data)) {
          // 将后端自定义成功 code（例如 300）也视为成功
          if ((data as any).success || (data as any).code === 200 || (data as any).code === 300) {
            return response
          } else {
            // 业务错误处理
            const message = (data as any).message || '请求失败'
            console.error('Business error:', message)
            return Promise.reject(new Error(message))
          }
        }

        // 如果不是 ApiResponse（例如直接返回 token 或其他对象），视为成功，直接返回响应
        return response
      },
      (error: AxiosError) => {
        // 隐藏loading
        console.log('Loading end...')

        // HTTP错误处理
        let message = '网络错误'

        if (error.response) {
          const { status, data } = error.response
          switch (status) {
            case 401:
              message = '未授权，请重新登录'
              // 清除token并跳转到登录页（项目登录路由为 `/`）
              localStorage.removeItem('token')
              window.location.href = '/'
              break
            case 403:
              message = '拒绝访问'
              break
            case 404:
              message = '请求地址不存在'
              break
            case 500:
              message = '服务器内部错误'
              break
            default:
              message = (data as any)?.message || `请求失败 (${status})`
          }
        } else if (error.request) {
          message = '网络连接失败'
        }

        console.error('HTTP error:', message)

        // 显示错误信息
        const customConfig = error.config as RequestConfig
        if (customConfig?.showError !== false) {
          // 这里可以集成消息提示组件
          console.error('Error message:', message)
        }

        return Promise.reject(new Error(message))
      }
    )
  }

  // GET请求
  async get<T = any>(url: string, config?: RequestConfig): Promise<ApiResponse<T>> {
    const response = await this.instance.get(url, config)
    return response.data
  }

  // GET请求（返回完整响应对象）
  async getWithResponse<T = any>(url: string, config?: RequestConfig): Promise<AxiosResponse<ApiResponse<T>>> {
    return await this.instance.get(url, config)
  }

  // POST请求
  async post<T = any>(url: string, data?: any, config?: RequestConfig): Promise<ApiResponse<T>> {
    const response = await this.instance.post(url, data, config)
    return response.data
  }

  // PUT请求
  async put<T = any>(url: string, data?: any, config?: RequestConfig): Promise<ApiResponse<T>> {
    const response = await this.instance.put(url, data, config)
    return response.data
  }

  // DELETE请求
  async delete<T = any>(url: string, config?: RequestConfig): Promise<ApiResponse<T>> {
    const response = await this.instance.delete(url, config)
    return response.data
  }

  // PATCH请求
  async patch<T = any>(url: string, data?: any, config?: RequestConfig): Promise<ApiResponse<T>> {
    const response = await this.instance.patch(url, data, config)
    return response.data
  }

  // 上传文件
  async upload<T = any>(url: string, file: File, config?: RequestConfig): Promise<ApiResponse<T>> {
    const formData = new FormData()
    formData.append('file', file)

    const response = await this.instance.post(url, formData, {
      ...config,
      headers: {
        'Content-Type': 'multipart/form-data',
        ...config?.headers
      }
    })
    return response.data
  }

  // 下载文件
  download(url: string, filename?: string, config?: RequestConfig): Promise<void> {
    return this.instance.get(url, {
      ...config,
      responseType: 'blob'
    }).then((response) => {
      const blob = new Blob([response.data])
      const downloadUrl = window.URL.createObjectURL(blob)
      const link = document.createElement('a')
      link.href = downloadUrl
      link.download = filename || 'download'
      document.body.appendChild(link)
      link.click()
      document.body.removeChild(link)
      window.URL.revokeObjectURL(downloadUrl)
    })
  }

  // 取消请求
  cancelRequest(message?: string) {
    const source = axios.CancelToken.source()
    source.cancel(message || '请求已取消')
    return source.token
  }
}

// 创建实例
const http = new HttpClient()

export default http
